package com.ctshk.rpc.payment.utils.mastercard;

import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.rpc.payment.dto.MasterCardPayConfig;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class ApiService {

    private static final Logger logger = LoggerFactory.getLogger(ApiService.class);


    /**
     * Execute HTTP method for the HTTP client and Host configuration
     * Configure for either API password or certificate authentication
     *
     * @param httpMethod PUT, POST, or GET
     * @return body from API response
     * @throws Exception
     */
    public static String executeHTTPMethod(HttpRequestBase httpMethod, MasterCardPayConfig config) throws Exception {
        String body = "";
        try {
            // Set the proper authentication type - username/password or certificate authentication
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpClientContext httpClientContext = HttpClientContext.create();
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            // Load credentials
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(config.getApiUsername(), config.getApiPassword()));
            httpClientContext.setCredentialsProvider(credentialsProvider);
            // Execute the request
            HttpResponse response = httpClient.execute(httpMethod, httpClientContext);
            HttpEntity entity = response.getEntity();
            body = EntityUtils.toString(entity);
            checkForRESTErrorResponse(body);
        } catch (IOException ioe) {
            // we can replace a specific exception that suits your application
            throw new Exception(ioe);
        } finally {
            httpMethod.releaseConnection();
        }
        return body;
    }

    /**
     * Checks if the API response contains an error (handles JSON response from REST call)
     *
     * @param response from the API call
     * @throws
     */
    private static void checkForRESTErrorResponse(String response) throws ApiException {
        JsonObject json = new Gson().fromJson(response, JsonObject.class);
        if (json.has("error")) {
            JsonObject errorJson = json.get("error").getAsJsonObject();
            logger.error(errorJson.toString());
            throw new BusinessException(SystemError.PAY_22003);
        }
    }
}
